#if 0
在设计的过程中常忘记写返回值，导致常常出问题
还有一种是RETURN_VAL_IF_FAIL，这种是有异常的时候才返回
所以，需要在后面添上正常情况的返回值，这里很容易漏掉
#endif
#include "c.h"
#include "memmgr2.h"

//#define DISABLE_SHOW_VALUE
#define DISABLE_D__

#include "debug.h"

#define Memory_Size_512K			(1<<19)
#define Memory_Size_1M				(1<<20)
#define Memory_Size_4M				(1<<22)
#define Global_Pool_Size 			Memory_Size_1M
#define Min_Data_Size 				4

#define Max_Chain_Array_Length 		15

#define Max_Large_Size				Memory_Size_4M
#define Max_Chain_Block_Size 		Memory_Size_512K
#define Min_Chain_Block_Size        32


#define Pointer_In_Zone(ptr,left,right)	\
	((char*)(ptr)-(char*)(left)>=0 && (char*)(ptr)-(char*)(right)<=0)
	
struct descriptor {
	const char *file;
	const char *func;
	 int 		line;
	 int 		size;
	struct descriptor *next;
};

struct memory_pool {
	char		*end;
	char 		*last;
	int  		failed;
	struct memory_pool *current;
	struct memory_pool *next;
};

struct memory_chain {
	struct descriptor *deactive;
	struct descriptor *active;
	int 	block_size;
};

static struct memory_manager {
	struct 	memory_pool *pool;
	struct 	descriptor 	*large;
	int 	max_block_size;
	
	int     large_count;
	int     pool_count;
	
	int     allocate_from_large_stamp;
	int     allocate_from_pool_stamp;
	int 	allocate_from_chain_stamp;
	
	long long     	allocate_memory_stamp;//pool+large
	long long       allocate_data_stamp;//memory_new size sum
	double  		ratio;
	struct memory_chain chain[Max_Chain_Array_Length];
}g_mmgr;

//暂时不考虑内存对齐的问题
union align {
	int i;
	long l;
	long *lp;
	void *p;
	void (*fp)(void);
	float f;
	double d;
	long double ld;
};

static struct memory_pool *alloc_memory_pool(void);
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static inline void inc_alloc_memory_stamp(int size)
{
	return_if_fail(size>=Min_Data_Size);
	g_mmgr.allocate_memory_stamp += size;
	if(g_mmgr.allocate_memory_stamp)
	g_mmgr.ratio=1.0*g_mmgr.allocate_data_stamp/g_mmgr.allocate_memory_stamp;
}

static inline void inc_alloc_data_stamp(int size)
{
	return_if_fail(size>=Min_Data_Size);
	g_mmgr.allocate_data_stamp += size;
	if(g_mmgr.allocate_memory_stamp)
	g_mmgr.ratio=1.0*g_mmgr.allocate_data_stamp/g_mmgr.allocate_memory_stamp;
}

#define Union_Align_Size 			(sizeof(union align))
#define Align_Size(size) 			(Round_Up((size),Union_Align_Size))
#define Desptr_Size 				(sizeof(struct descriptor))
#define PDesptr_Size				(sizeof(struct descriptor*))
#define Data_Package_Size(size) 	(Align_Size(size)+Desptr_Size)
#define Desptr_Package_Size(desptr)	(Data_Package_Size(desptr->size))
#define Min_Package_Size 			(Data_Package_Size(Min_Data_Size))
#define Data_Addr_of_Pool(pool) 	(char*)((char*)pool+sizeof *(pool))
#define Pool_End(pool)				(char*)((char*)(pool)+Global_Pool_Size)


//保证是对齐后的
void *sys_new(int size)
{
	return_val_if_fail(size >= Min_Data_Size,0);
	void *ptr=calloc(1,size);
	return_val_if_fail(ptr!=0 , 0);
	inc_alloc_memory_stamp(size);
	return ptr;
}

void sys_free(void *ptr)
{
	return_if_fail(ptr!=0);
	if(ptr != 0)free(ptr);
}

static int init_memory_manager(void)
{
	Zero_Memory(&g_mmgr);
	struct memory_pool *pool=alloc_memory_pool();
	return_val_if_fail(pool!=0 , -1);
	int i;
	int chain_block_size=Min_Chain_Block_Size;
	struct memory_chain *chain=g_mmgr.chain;
	for(i=0 ; i<Max_Chain_Array_Length ; i++){
		chain[i].block_size=chain_block_size;
		chain_block_size <<= 1;
	}
	return_val_if_fail(
		chain[i-1].block_size <= Max_Chain_Block_Size , -1
	);
	g_mmgr.max_block_size=chain[i-1].block_size;
	return 0;
}

//size has been aligned
#define Enough_Space_for_Alloc(pool,size) \
	( (char*)((pool)->last + (size)) <= Pool_End(pool))

#define Set_Desptr(desptr,_file,_func,_line,_size) do { \
			desptr->file=_file;\
			desptr->func=_func;\
			desptr->line=_line;\
			desptr->size=_size;\
		} while(0)

#define Ptr_Entry_Desptr(ptr) 		((struct descriptor*)((char*)(ptr)-Desptr_Size))
#define Desptr_Entry_Ptr(desptr) 	((char*)((char*)(desptr)+sizeof *(desptr)))

#define Show_Desptr(message,desptr)	do { \
		fprintf(stdout,"\n%s\n",message);\
		Show_Value(desptr->file,s);\
		Show_Value(desptr->func,s);\
		Show_Value(desptr->line,d);\
		Show_Value(desptr->size,d);\
	}while(0)
	
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
typedef int (*compare_func)(void *data,void *val);
typedef void **(*entry_next_func)(void *data);

int default_compare(void *data,void *val)
{
	return (int)((char*)data-(char*)val);
}

static void ** search_slist(
	void **head,
	int (*compare)(void *data,void *val),
	void **(*entry_next)(void *data),
	void *val
)
{
	void **pp = 0;
	for(pp = head; pp && *pp; pp = entry_next(*pp))
		if(compare(*pp,val) == 0) break;
	return pp;
}

static inline struct memory_pool **entry_next_pool(struct memory_pool *pool)
{
	return pool ? &pool->next : 0;
}

static inline struct descriptor **entry_next_desptr(struct descriptor *desptr)
{
	return desptr ? &desptr->next : 0;
}

static int compare_pool_for_enough_space(
	struct memory_pool *pool , int size_package)
{
	if(Enough_Space_for_Alloc(pool,size_package)) return 0;
	if(pool->failed++>4) pool->current = pool->next;
	return -1;
}

static struct memory_pool *search_pool_for_enough_space(int size_package)
{
	return_val_if_fail(
		size_package >= Min_Package_Size 
	 && size_package <= g_mmgr.max_block_size,
		0,
		"Allocate Size Not In Normal Range , "
		"%d out of [ %d , %d ]",
		size_package , Min_Package_Size , 
		g_mmgr.max_block_size
	);
	void **pp = search_slist(
		(void			**	)&g_mmgr.pool->current,
		(compare_func		)compare_pool_for_enough_space,
		(entry_next_func	)entry_next_pool,
		(void			*	)size_package
	) ;
	return *(struct memory_pool **)pp ;
}

static int compare_pool_for_desptr(struct memory_pool *pool, 
									struct descriptor *desptr)
{
	void *left = Data_Addr_of_Pool(pool);
	void *right = pool->last-Min_Package_Size;
	if(Pointer_In_Zone(desptr,left, right)) return 0;
	return -1;
}

static struct memory_pool *search_pool_for_desptr(struct descriptor *desptr)
{
	return_val_if_fail(desptr != 0 , 0);
	void **pp = search_slist(
		(void			**	)&g_mmgr.pool,
		(compare_func		)compare_pool_for_desptr,
		(entry_next_func	)entry_next_desptr,
		(void			*	)desptr
	);
	return *(struct memory_pool **)pp;
}

static struct descriptor **search_large_for_desptr(struct descriptor *desptr)
{
	return_val_if_fail(desptr != 0, 0);
	void **pp = search_slist(
		(void			**	)&g_mmgr.large,
		(compare_func		)default_compare,
		(entry_next_func	)entry_next_desptr,
		(void			*	)desptr
	);
	return (struct descriptor**)pp;
}

static struct memory_chain *search_chain_for_data_size(int size_data)
{
	int size_package=Data_Package_Size(size_data);
	return_val_if_fail(
		size_package >= Min_Package_Size 
	 && size_package <= g_mmgr.max_block_size,
		0,
		"There is no Chain for Such Data Package Size"
		" , %d out of [ %d , %d ]",
		size_package , Min_Package_Size , g_mmgr.max_block_size
	);
	struct memory_chain *chain=g_mmgr.chain;
	int i;
	for(i=0 ; i < Max_Chain_Array_Length ; i++){
		if(chain[i].block_size >= size_package) 
			return &chain[i];
	}
	return 0;
}

static struct memory_chain *search_chain_for_desptr(struct descriptor *desptr)
{
	return desptr ? search_chain_for_data_size(desptr->size) : 0;
}

static struct descriptor **search_active_for_desptr(
	struct memory_chain *chain , struct descriptor *desptr)
{
	return_val_if_fail(chain != 0 , 0);
	return_val_if_fail(desptr != 0 , 0);
	
	void **pp = search_slist(
		(void      **	)		&chain->active,
		(compare_func	)		default_compare,
		(entry_next_func)		entry_next_desptr,
		(void		*	)		desptr
	);
	return (struct descriptor **)pp;
}

static struct descriptor **search_chain_active_for_desptr(struct descriptor *desptr)
{
	struct memory_chain *chain=search_chain_for_desptr(desptr);
	return_val_if_fail(chain != 0 , 0);
	return search_active_for_desptr(chain,desptr);
}

static struct descriptor **search_chain_deactive_for_desptr(struct descriptor *desptr)
{
	struct memory_chain *chain=search_chain_for_desptr(desptr);
	return_val_if_fail(chain!=0 , 0);
	void **pp = search_slist(
		(void      **	)		&chain->deactive,
		(compare_func	)		default_compare,
		(entry_next_func)		entry_next_desptr,
		(void		*	)		desptr
	);
	return (struct descriptor **)pp;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static int desptr_add2_chain_active(struct descriptor *desptr)
{
	return_val_if_fail(desptr != 0 , -1);
	struct memory_chain *chain=search_chain_for_desptr(desptr);
	return_val_if_fail(chain != 0 , -1);
	desptr->next = chain->active;
	chain->active = desptr;
	return 0;
}

#define Clear_Desptr(desptr,size)  	Bzero(Desptr_Entry_Ptr(desptr),(size)-sizeof *(desptr))

static int desptr_add2_chain_deactive(struct descriptor *desptr,struct memory_chain *chain)
{
	return_val_if_fail(desptr!=0,-1);
	return_val_if_fail(chain!=0,-1);
	Clear_Desptr(desptr,chain->block_size);
	desptr->next=chain->deactive;
	chain->deactive=desptr;
	return 0;
}

static int desptr_add2_deactive(struct descriptor *desptr)
{
	return_val_if_fail(desptr!=0,-1);
	struct memory_chain *chain=search_chain_for_desptr(desptr);
	return_val_if_fail(chain!=0,-1);
	return desptr_add2_chain_deactive(desptr,chain);
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static struct memory_pool *alloc_memory_pool(void)
{
	struct memory_pool *pool=sys_new(Global_Pool_Size);
	return_val_if_fail(pool!=0,0);
	g_mmgr.pool_count++;
	pool->last=Data_Addr_of_Pool(pool);
	pool->end=Pool_End(pool);
	pool->current=pool;
	pool->failed=0;
	pool->next=g_mmgr.pool;
	g_mmgr.pool=pool;
	return pool;
}

//数据大小，所以需要内部对其
static void *alloc_from_large(int size_data,
	const char *file , const char *func , const int line)
{
	return_val_if_fail(size_data >= Min_Data_Size,0);
	int size_package = Data_Package_Size(size_data);
	return_val_if_fail(
		size_package >  g_mmgr.max_block_size
	 &&	size_package <= Max_Large_Size,
		0,
		"Allocate Data Package Size Not In The Normal Range"
		" , %d Out of [ %d , %d ] .",
		size_package , g_mmgr.max_block_size , Max_Large_Size
	);
	struct descriptor *desptr=(struct descriptor*)sys_new(size_package);
	return_val_if_fail(desptr!=0,0,"Allocate Large Memory Failed");
	Set_Desptr(desptr,file,func,line,size_data);
	desptr->next=g_mmgr.large;
	g_mmgr.large=desptr;
	g_mmgr.large_count++;
	g_mmgr.allocate_from_large_stamp++;
	inc_alloc_data_stamp(size_data);
	return Desptr_Entry_Ptr(desptr);
	/*
	以下函数在sys_new中就自动设置了
	int_alloc_memory_stamp(size_package);
	*/
}

#if 0
一个bug,在pool中申请内存时通常是因为chain deactive中没有，此时不能传入size_Data
给pool,应按size_data在chain中的block_size传，否则pool会按Data_Package_Size分，
造成分配过小，这样容易造成数据覆盖
注意分清size_data,size_package,size_block区别
#endif
//数据大小，内部对齐
static void *alloc_from_pool(int size_data ,
	const char *file , const char *func , int line)
{
	int size_package = Data_Package_Size(size_data);
	struct memory_chain *chain=search_chain_for_data_size(size_data);
	int size_block = chain->block_size;
	return_val_if_fail(chain!=0,0,"Chain For Data Size Null");
	return_val_if_fail(
		size_package >= Min_Package_Size
	 &&	size_package <= g_mmgr.max_block_size,
		0,
		"Allocate Data Package Size Not In The Normal Range"
		" , %d Out of [ %d , %d ] .",
		size_package , Min_Package_Size , g_mmgr.max_block_size
	);
	struct memory_pool *pool=search_pool_for_enough_space(size_block);
	if( pool == 0) pool = alloc_memory_pool();
	return_val_if_fail(pool != 0 , 0);
	return_val_if_fail(
		Enough_Space_for_Alloc(pool,size_block),0);
	struct descriptor *desptr = (struct descriptor*)pool->last;
	pool->last += size_block;
	return_val_if_fail(pool->last <= Pool_End(pool) , 0);
	Set_Desptr(desptr,file,func,line,size_data);
	int ret = desptr_add2_chain_active(desptr);
	return_val_if_fail(ret == 0 , 0);
	inc_alloc_data_stamp(size_data);
	g_mmgr.allocate_from_pool_stamp++;
	return Desptr_Entry_Ptr(desptr);
}

static void *alloc_from_chain_deactive(int size_data,
	const char *file , const char *func , const int line)
{
	return_val_if_fail(size_data >= Min_Data_Size,0,
		"Data Size Lower Than %d .", size_data , Min_Data_Size);
	int size_package = Data_Package_Size(size_data);
	return_val_if_fail(
		size_package >= Min_Package_Size
	 &&	size_package <= g_mmgr.max_block_size,
		0,
		"Allocate Data Package Size Not In The Normal Range"
		" , %d Out of [ %d , %d ] .",
		size_package , Min_Package_Size , g_mmgr.max_block_size
	);

	struct memory_chain *chain=search_chain_for_data_size(size_data);
	return_val_if_fail( chain!=0, 0 , 
		"No Chain For Such Data Size %d ." , size_data);
	struct descriptor *desptr=chain->deactive;
	if(desptr == 0) return desptr;

	chain->deactive=desptr->next;
	Set_Desptr(desptr,file,func,line,size_data);
	desptr_add2_chain_active(desptr);

	g_mmgr.allocate_from_chain_stamp++;
	inc_alloc_data_stamp(size_data);

	return Desptr_Entry_Ptr(desptr);
}

void *memory_new(int size_data,
	const char *file , const char *func , const int line)
{
	fprintf(stdout,"\nAllocate Memory :");
	fprintf(stdout,"\n<< : In %s %s Line %d , Alloc Size = %d .",
		file , func , line , size_data);
	if(g_mmgr.pool==0 && g_mmgr.large==0)
		init_memory_manager();	
		
	if(size_data < Min_Data_Size) {
		fprintf(stdout,"\n>> : Failed , Data Size %d Lower Than %d",
			size_data , Min_Data_Size );
		return 0;
	}
		
	int size_package = Data_Package_Size(size_data);
	if( size_package < Min_Package_Size
	 	||	size_package > Max_Large_Size){
		fprintf(stdout,"\n>> : Failed , Package Size Not Normal"
		" , %d Out of [ %d , %d ] .",
		size_package , Min_Package_Size , Max_Large_Size);
		return 0;
	}
	void *ptr=0;
	if(size_package > g_mmgr.max_block_size
		&& size_package <= Max_Large_Size ){
		ptr=alloc_from_large(size_data,file,func,line);
		fprintf(stdout,"\n>> : %s , From Large "
				", Addr = %p , Pkg_Size = %d ." , 
				ptr ? "Succeed" : "Failed" , ptr , size_package );
		return ptr;
	}
	
	struct descriptor *desptr = 0 ;
	struct memory_chain *chain = 0;
	ptr=alloc_from_chain_deactive(size_data,file,func,line);
	if(ptr != 0) {
		desptr = Ptr_Entry_Desptr(ptr);
		chain=search_chain_for_desptr(desptr);
		if(chain == 0) {
			fprintf(stdout,"\n>> : Failed , Allocate Process Exception .");
			return 0;
		}
		fprintf(stdout,"\n>> : Succeed , From Chain "
				", Addr = %p , Pkg_Size = %d / %d / %d ." , 
				ptr , desptr->size , size_package , chain->block_size );		
		return ptr;
	}
D__
	ptr=alloc_from_pool(size_data , file , func , line);
	if(ptr != 0) {
		desptr = Ptr_Entry_Desptr(ptr);
		chain=search_chain_for_desptr(desptr);
		if(chain == 0) {
			fprintf(stdout,"\n>> : Failed , Allocate Process Exception .");
			return 0;
		}
		fprintf(stdout,"\n>> : Succeed , From Pool "
				", Addr = %p , Size = %d / %d / %d ." ,
				ptr , desptr->size , size_package , chain->block_size );
		
		return ptr;
	}	
	fprintf(stdout,"\n>> : Failed , Allocate Process Exception .");
	return ptr;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static int memory_free_large( struct descriptor *desptr,
	const char *file , const char *func , const int line)
{
	return_val_if_fail(desptr != 0 , -1);
	#if 0
	只有当在POOL中找不到时才会从Large中找，这时无法判定desptr是否是
	合法内存，故不能随便引用desptr->size，可能导致异常
	int size_package=Data_Package_Size(desptr->size);
	return_if_fail(
		size_package > g_mmgr.max_block_size,
		-1,
		"Desptr Not Large , Size Only %d",
		desptr->size
	);
	#endif
	struct descriptor **pp = search_large_for_desptr(desptr);
	return_val_if_fail( pp && *pp==desptr , -1);
	*pp = (*pp)->next ;
	sys_free(desptr);
	g_mmgr.large_count--;
	return 0;
}

static int memory_free_chain_active(struct descriptor *desptr,
	const char *file , const char *func , const int line)
{
	return_val_if_fail(desptr != 0 , -1);
	struct descriptor **pp=search_chain_active_for_desptr(desptr);
	return_val_if_fail( pp!=0 && *pp == desptr , -1);
	*pp = (*pp)->next;
	desptr_add2_deactive(desptr);
	return 0;		
}

int memory_free(void *ptr ,
	const char *file , const char *func , const int line)
{
	fprintf(stdout,"\nRelease Memory :");
	fprintf(stdout,"\n<< : In %s %s Line %d , Ptr Addr = %p . ",
		file , func , line , ptr);
	if(g_mmgr.pool==0 && g_mmgr.large==0)
		init_memory_manager();
	
	if(ptr==0) {
		fprintf(stdout,"\n>> : Failed , Release Ptr is Null . ");
		return -1;
	}
	struct descriptor *desptr = Ptr_Entry_Desptr(ptr);
	struct memory_pool *pool  = search_pool_for_desptr(desptr);
	if(pool==0){
		int ret=memory_free_large(desptr,file,func,line);
		if(ret!=0){
			fprintf(stdout,"\n>> : Failed , Addr = %p Not Exist .",ptr);
			return -1;
		}
	/*
		下面这句return 0极其重要，因为上面如果ret=0，那么断言不会出发，
		就会向下执行，因为desptr在memory_free_large中已经释放了，所以
		在调用下面的函数过程中会发生错误，下面memory_free_chain_active
		后面也有一个return 0,一定要注意，这时RETURN_IF_FAIL类的断言很容易
		出错的地方
	*/
		fprintf(stdout,"\n>> : Succeed , From Large , System Works Pretty Well .");
		return 0;
	}
	int ret=memory_free_chain_active(desptr,file,func,line);
	if(ret!=0){
		fprintf(stdout,"\n>> : Failed , Addr = %p Not Exist .",ptr);
		return -1;
	}
	fprintf(stdout,"\n>> : Succeed , From Chain , System Works Pretty Well .");
	return 0;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
void *memory_resize(void *ptr , int size_data,
	const char *file , const char *func , const int line)
{
	fprintf(stdout,"\nReallocate Memory :");
	fprintf(stdout,"\n<< : In %s %s Line %d , "
			  "Addr = %p , New Size = %d . ",
			file , func , line , ptr , size_data);
	if(g_mmgr.pool==0 && g_mmgr.large==0)
		init_memory_manager();
	if(ptr==0) {
		fprintf(stdout,"\n>> : Failed , Realloc Ptr is Null .");
		return ptr;
	}
	if(size_data<Min_Data_Size) {
		fprintf(stdout,"\n>> : Failed , Realloc Size_Data Lower Than Normal Range .");
		return ptr;
	}
	struct descriptor *desptr=Ptr_Entry_Desptr(ptr);
	struct memory_pool *pool=search_pool_for_desptr(desptr);
	struct descriptor **pp_large=0;
	struct descriptor **pp_chain=0;
	int old_size=0;
	int new_size=Data_Package_Size(size_data);
	if(pool==0) {
D__
		pp_large = search_large_for_desptr(desptr);
		if(*pp_large != desptr ) {
			fprintf(stdout,"\n>> : Failed , Addr = %p Not Exist .", ptr);
			return ptr;
		}
		old_size=Data_Package_Size(desptr->size);
		if(old_size >= new_size) {
			fprintf(stdout,"\n>> : Succeed , Ptr Not Changed , "
			"Original Size = %d .", desptr->size );
			return ptr;
		}
		*pp_large = (*pp_large)->next;
	}
	else {
D__
		struct memory_chain *chain=search_chain_for_desptr(desptr);
		if(chain == 0) {
			fprintf(stdout,"\n>> : Failed , Addr = %p Not Exist .",ptr);
			return ptr;
		}
D__
		pp_chain = search_active_for_desptr(chain,desptr);
		if( pp_chain == 0 || *pp_chain != desptr ) {
			fprintf(stdout,"\n>> : Failed , Addr = %p Not Exist .",ptr);
			return ptr;
		}
D__
		if(new_size <= chain->block_size) {
			fprintf(stdout,"\n>> : Succeed , Ptr Not Changed Yet , "
			"Chain Block Size = %d" , chain->block_size);
			return ptr;
		}
		*pp_chain = (*pp_chain)->next;
	}
	void *new_ptr=memory_new(size_data,file,func,line);
	struct descriptor *new_desptr = Ptr_Entry_Desptr(new_ptr);
D__
	Show_Value(new_desptr->size,d);
	if(new_ptr == 0) {
		fprintf(stdout,"\n>> : Failed , Reallocate Process Exception .");
		return ptr;
	}
D__
	memcpy(new_ptr , ptr , Min(desptr->size , size_data));
	new_desptr = Ptr_Entry_Desptr(new_ptr);
	if(pp_large != 0) {
D__
		sys_free(desptr);
		g_mmgr.large_count--;
	}
	else if(pp_chain != 0) {
D__	
		desptr_add2_deactive(desptr);
	}	
	new_desptr = Ptr_Entry_Desptr(new_ptr);
	fprintf(stdout,"\n>> : Succeed , Ptr Addr = %p . "
		"System Works Pretty Well ." , new_ptr);
	return new_ptr; 
}

const char *memory_status_string(void *ptr)
{
	return_val_if_fail(ptr!=0,0,"Ptr Null"); 
	struct descriptor **pp;
	struct descriptor *desptr = Ptr_Entry_Desptr(ptr);
D__
	struct memory_pool *pool=search_pool_for_desptr(desptr);
D__
	if(pool != 0) {
		if((char*)desptr >= (char*)pool->last) 
			return "Memory_In_Pool";
D__
		pp=search_chain_active_for_desptr(desptr);
		if(pp != 0 && *pp != 0) return "Memory_Allocated";
D__
		pp=search_chain_deactive_for_desptr(desptr);
		if(pp != 0 && *pp != 0) return "Memory_Released";
		
		return "Memory_Invalid"; 
	}
D__
	pp=search_large_for_desptr(desptr);
	if(*pp) return "Memory_Allocated_In_Large";
	return "Memory_Invalid";
}

static void memory_show_leaking(struct descriptor *desptr)
{
	if(desptr==0) return;
	fprintf(stdout, "\n>> : %s %s Line %d , "
		"Ptr Addr = %p , Size = %d . ",
		desptr->file , desptr->func , desptr->line , 
		Desptr_Entry_Ptr(desptr) , desptr->size);
}

void memory_leaking_check(void)
{	
	int flag=0;
	struct descriptor *desptr=g_mmgr.large;
	struct descriptor *next;
	for( ; desptr!=0 ;desptr = next) {
		if(flag==0){
			fprintf(stdout,"\nMemory Leaking Danger :");
			flag=1;
		}
		next = desptr->next;
		memory_show_leaking(desptr);
		sys_free(desptr);
		g_mmgr.large_count--;
	}
	int i;
	struct memory_chain *chain=g_mmgr.chain;
	for(i=0 ; i<Max_Chain_Array_Length ; i++)
		for( desptr=chain[i].active ; desptr ; desptr=desptr->next) {
			if(flag==0){
				fprintf(stdout,"\nMemory Leaking Danger :");
				flag=1;
			}
			memory_show_leaking(desptr);
		}
	struct memory_pool *pool=g_mmgr.pool,*next_pool;
	for( ; pool ; pool = next_pool ) {
		next_pool=pool->next;
		sys_free(pool);
		g_mmgr.pool_count--;
	}
	if(g_mmgr.large_count != 0) 
		fprintf(stdout,"\n>> : Strange Exception Exist , Large Count None Zero");
	if(g_mmgr.pool_count != 0) 
		fprintf(stdout,"\n>> : Strange Exception Exist , Pool Count None Zero");
	Zero_Memory(&g_mmgr);
	fprintf(stdout,"\n");
}

void memory_show()
{
	Show_Value(g_mmgr.large_count,d);
	Show_Value(g_mmgr.pool_count,d);
	Show_Value(g_mmgr.allocate_from_large_stamp,d);
	Show_Value(g_mmgr.allocate_from_pool_stamp,d);
	Show_Value(g_mmgr.allocate_from_chain_stamp,d);
	Show_Value(g_mmgr.allocate_memory_stamp,lld);
	Show_Value(g_mmgr.allocate_data_stamp,lld);
	Show_Value(g_mmgr.ratio,lf);
}
